#include "bsp_lcd.h"
#include "bsp_system_clock.h"
#include "string.h"


//将数据定义到SDRAM中
uint16_t lcd_frame_buf[800][480] __attribute__((section(".bss.ARM.__at_0XC0000000")));

static void lcd_rst(uint8_t en){
	gpio_bit_write(GPIOD,GPIO_PIN_13,en);
}
static void lcd_bl(uint8_t en){
	gpio_bit_write(GPIOD,GPIO_PIN_12,en);
}

lcd_rgb_t lcd_rgb_info = {
	.width = 800,
	.height = 480,
	.hbp = 46,
	.hfp = 210,
	.vbp = 23,
	.vfp = 22,
	.hsw = 1,
	.vsw = 1,
	.ppf = LAYER_PPF_RGB565,
	.acf1 = LAYER_ACF1_PASA,
	.acf2 = LAYER_ACF2_PASA,
	.backcolor.red = 0x00,
	.backcolor.green = 0x00,
	.backcolor.blue = 0x00,
	.backcolor.alpha = 255,
	.layer0.red = 0x00,
	.layer0.green = 0x00,
	.layer0.blue = 0x00,
	.layer0.alpha = 255,
	.rst = lcd_rst,
	.bl = lcd_bl,
	.delay = delay_ms,
};

static void bsp_lcd_gpio_config(void){
	
	rcu_periph_clock_enable(RCU_TLI);
	
	rcu_periph_clock_enable(RCU_GPIOA);
	rcu_periph_clock_enable(RCU_GPIOB);
	rcu_periph_clock_enable(RCU_GPIOC);
	rcu_periph_clock_enable(RCU_GPIOD);
	rcu_periph_clock_enable(RCU_GPIOF);
	rcu_periph_clock_enable(RCU_GPIOG);
	
	//RGB数据引脚配置
#if 1
	gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_0);
	gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_0);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_0);
	
	gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_11);
	gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
	gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_11);
	
	gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_12);
	gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
	gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_12);
	
	gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_8);
	gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
	gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_8);
	
	gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_6);
	gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
	gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_6);//
	
	gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_6);
	gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
	gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_6);
	
	gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_10);
	gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
	gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_10);
	
	gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_10);
	gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_10);
	
	gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_11);
	gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_11);
	
	gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_7);
	gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
	gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_7);
	
	gpio_af_set(GPIOD, GPIO_AF_14, GPIO_PIN_3);
	gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
	gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_3);//
	
	gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_11);
	gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
	gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_11);
	
	gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_12);
	gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
	gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_12);
	
	gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_3);
	gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
	gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_3);
	
	gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_8);
	gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_8);
	
	gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_9);
	gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_9);
#endif

	//控制引脚
#if 1
	gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_7);
	gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
	gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_7);
	
	gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_6);
	gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
	gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_6);
	
	gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_4);
	gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4);
	gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_4);
	
	gpio_af_set(GPIOF, GPIO_AF_14, GPIO_PIN_10);
	gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
	gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_10);
#endif
	gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_13);
	gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13);

	gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_12);
	gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);
}

static void bsp_lcd_fill_init(uint32_t color){
	//默认是横屏
	ipa_destination_parameter_struct  ipa_destination_init_struct;
	rcu_periph_clock_enable(RCU_IPA);
	ipa_deinit();
	ipa_pixel_format_convert_mode_set(IPA_FILL_UP_DE);//像素格式转换模式，用特定的颜色格式来填充目标存储区
	
	ipa_destination_init_struct.destination_memaddr = (uint32_t)lcd_frame_buf;
	ipa_destination_init_struct.destination_lineoff = lcd_rgb_info.width;
	ipa_destination_init_struct.destination_prealpha = lcd_rgb_info.layer0.alpha;
	ipa_destination_init_struct.destination_pf = IPA_DPF_RGB565;
	ipa_destination_init_struct.destination_prered = (color & 0xF800) >> 11;
	ipa_destination_init_struct.destination_pregreen = (color & 0x07E0) >> 5;
	ipa_destination_init_struct.destination_preblue = color & 0x1F;
	ipa_destination_init_struct.image_width = lcd_rgb_info.width;
	ipa_destination_init_struct.image_height = lcd_rgb_info.height;
	
	ipa_destination_init(&ipa_destination_init_struct);
	ipa_transfer_enable();
	
	while(ipa_interrupt_flag_get(IPA_INT_FLAG_FTF) == RESET){
	};
	ipa_interrupt_flag_clear(IPA_INT_FLAG_FTF);
}
static void bsp_tli_clk_config(void){ //ILI6122最大支持50Mhz,设置为30Mhz
	uint16_t retry = 0;
	
	rcu_osci_off(RCU_PLLSAI_CK);
	while((SUCCESS == rcu_osci_stab_wait(RCU_PLLSAI_CK)) && (retry < 0X1FFF)){
		retry++;
	}
	if(retry != 0x1FFF){
		rcu_pllsai_config(480, 4, 4);
		rcu_tli_clock_div_config(RCU_PLLSAIR_DIV4);
		rcu_osci_on(RCU_PLLSAI_CK);
		rcu_osci_stab_wait(RCU_PLLSAI_CK);
	}
}
static void bsp_exmc_config(void){
	exmc_norsram_parameter_struct  nor_init_struct;
	exmc_norsram_timing_parameter_struct  sram_timing_read;
	exmc_norsram_timing_parameter_struct  sram_timing_write;
	
	rcu_periph_clock_enable(RCU_EXMC);
	
	sram_timing_read.asyn_access_mode = EXMC_ACCESS_MODE_A;
	sram_timing_read.syn_data_latency = EXMC_DATALAT_2_CLK;
	sram_timing_read.syn_clk_division = EXMC_SYN_CLOCK_RATIO_DISABLE;
	sram_timing_read.bus_latency = 0;

	sram_timing_read.asyn_data_setuptime = 90;
	sram_timing_read.asyn_address_holdtime = 0;
	sram_timing_read.asyn_address_setuptime = 15;

	sram_timing_write.asyn_access_mode = EXMC_ACCESS_MODE_A;
	sram_timing_write.syn_data_latency = EXMC_DATALAT_2_CLK;
	sram_timing_write.syn_clk_division = EXMC_SYN_CLOCK_RATIO_DISABLE;
	sram_timing_write.bus_latency = 0;
	sram_timing_write.asyn_data_setuptime = 15;
	sram_timing_write.asyn_address_holdtime = 0;                  
	sram_timing_write.asyn_address_setuptime = 15;

	nor_init_struct.norsram_region = EXMC_BANK0_NORSRAM_REGION3;
	nor_init_struct.write_mode = EXMC_ASYN_WRITE;
	nor_init_struct.extended_mode = ENABLE;
	nor_init_struct.asyn_wait = DISABLE;
	nor_init_struct.nwait_signal = DISABLE;
	nor_init_struct.memory_write = ENABLE;
	nor_init_struct.nwait_config = EXMC_NWAIT_CONFIG_BEFORE;
	nor_init_struct.wrap_burst_mode = DISABLE;
	nor_init_struct.nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
	nor_init_struct.burst_mode = DISABLE;
	nor_init_struct.databus_width = EXMC_NOR_DATABUS_WIDTH_16B;
	nor_init_struct.memory_type = EXMC_MEMORY_TYPE_SRAM;
	nor_init_struct.address_data_mux = DISABLE;
	nor_init_struct.read_write_timing = &sram_timing_read;
	nor_init_struct.write_timing = &sram_timing_write;

	exmc_norsram_init(&nor_init_struct);

	exmc_norsram_enable(EXMC_BANK0_NORSRAM_REGION3);
}

void bsp_lcd_init(void){
	tli_parameter_struct               tli_init_struct;
	tli_layer_parameter_struct         tli_layer_init_struct;
	
	bsp_tli_clk_config();
	bsp_lcd_gpio_config();
	memset(lcd_frame_buf,0x00,sizeof(lcd_frame_buf));
	
	//外设初始化
	tli_init_struct.synpsz_vpsz = lcd_rgb_info.vsw - 1;
	tli_init_struct.synpsz_hpsz = lcd_rgb_info.hsw - 1;
	tli_init_struct.backpsz_vbpsz = lcd_rgb_info.vsw + lcd_rgb_info.vbp - 1;
	tli_init_struct.backpsz_hbpsz = lcd_rgb_info.hsw + lcd_rgb_info.hbp - 1;
	tli_init_struct.activesz_vasz = lcd_rgb_info.vsw + lcd_rgb_info.vbp + lcd_rgb_info.height - 1;
	tli_init_struct.activesz_hasz = lcd_rgb_info.hsw + lcd_rgb_info.hbp + lcd_rgb_info.width - 1;
	tli_init_struct.totalsz_vtsz = lcd_rgb_info.vsw + lcd_rgb_info.vbp + lcd_rgb_info.height + lcd_rgb_info.vfp - 1;
	tli_init_struct.totalsz_htsz = lcd_rgb_info.hsw + lcd_rgb_info.hbp + lcd_rgb_info.width + lcd_rgb_info.hfp - 1;
	tli_init_struct.backcolor_red = lcd_rgb_info.backcolor.red;
	tli_init_struct.backcolor_green = lcd_rgb_info.backcolor.green;
	tli_init_struct.backcolor_blue = lcd_rgb_info.backcolor.blue;
	tli_init_struct.signalpolarity_hs = TLI_HSYN_ACTLIVE_LOW;//水平同步脉冲低电平有效
	tli_init_struct.signalpolarity_vs = TLI_VSYN_ACTLIVE_LOW;//垂直同步脉冲低电平有效
	tli_init_struct.signalpolarity_de = TLI_DE_ACTLIVE_LOW;//数据使能低电平有效
	tli_init_struct.signalpolarity_pixelck = TLI_PIXEL_CLOCK_TLI;
	tli_init(&tli_init_struct);
	
	//图层初始化
	tli_layer_init_struct.layer_window_rightpos = lcd_rgb_info.width + lcd_rgb_info.hsw + lcd_rgb_info.hbp - 1;//窗口右侧位置
	tli_layer_init_struct.layer_window_leftpos = lcd_rgb_info.hsw + lcd_rgb_info.hbp;//窗口左侧位置
	tli_layer_init_struct.layer_window_bottompos = lcd_rgb_info.height + lcd_rgb_info.vsw + lcd_rgb_info.vbp - 1;//窗口底部位置
	tli_layer_init_struct.layer_window_toppos = lcd_rgb_info.vsw + lcd_rgb_info.vbp;//窗口顶部位置
	tli_layer_init_struct.layer_ppf = lcd_rgb_info.ppf;//像素格式
	tli_layer_init_struct.layer_sa = 255;//恒定透明值
	tli_layer_init_struct.layer_default_alpha = lcd_rgb_info.layer0.alpha;
	tli_layer_init_struct.layer_default_red = lcd_rgb_info.layer0.red;
	tli_layer_init_struct.layer_default_green = lcd_rgb_info.layer0.green;
	tli_layer_init_struct.layer_default_blue = lcd_rgb_info.layer0.blue;
	tli_layer_init_struct.layer_acf1 = lcd_rgb_info.acf1;
	tli_layer_init_struct.layer_acf2 = lcd_rgb_info.acf2;
	tli_layer_init_struct.layer_frame_bufaddr = (uint32_t)lcd_frame_buf;
	tli_layer_init_struct.layer_frame_buf_stride_offset = lcd_rgb_info.width*2;//帧缓存区步幅偏移
	tli_layer_init_struct.layer_frame_line_length = lcd_rgb_info.width*2+3;//帧行长度
	tli_layer_init_struct.layer_frame_total_line_number = lcd_rgb_info.height;//帧总行数
	tli_layer_init(LAYER0,&tli_layer_init_struct);
	
	tli_layer_enable(LAYER0);//使能0层
	tli_reload_config(TLI_REQUEST_RELOAD_EN);//立刻重载层设置
	tli_enable();//使能外设
	
	bsp_exmc_config();
	
	lcd_rgb_info.rst(1);
	lcd_rgb_info.delay(10);
	lcd_rgb_info.rst(0);
	lcd_rgb_info.delay(50);
	bsp_lcd_fill_init(0);
	lcd_rgb_info.delay(100);
	lcd_rgb_info.bl(1);
}

void bsp_lcd_set_point_color(uint16_t sx, uint16_t sy, uint32_t color){
	*(uint16_t *)((uint32_t)lcd_frame_buf[0] + 2 * (lcd_rgb_info.width * sy + sx)) = color;
}
